package stardust.product.utils.transmit;

import java.io.IOException;
import java.net.Socket;
import java.net.UnknownHostException;
import stardust.core.io.IOUtils;
import stardust.core.log.Log;

public class TransmitRelayConnector
{
  
  private Socket sourceSocket;
  private Socket targetSocket;
  
  private String remoteHost;
  private int remotePort;
  
  private TransmitRelaySender sender;
  private TransmitRelayReceiver receiver;
  
  private boolean printFlag;
  
  public TransmitRelayConnector(Socket sourceSocket, String remoteHost, int remotePort)
  {
    this.sourceSocket = sourceSocket;
    this.remoteHost = remoteHost;
    this.remotePort = remotePort;
  }
  
  public void connect() throws UnknownHostException, IOException
  {
    this.targetSocket = new Socket(this.remoteHost, this.remotePort);
    
    this.sourceSocket.setSoTimeout(TransmitListener.TIMEOUT);
    this.targetSocket.setSoTimeout(TransmitListener.TIMEOUT);
    
    this.sender = new TransmitRelaySender();
    this.receiver = new TransmitRelayReceiver();
    
    this.sender.start();
    this.receiver.start();
  }
  
  public void disconnect()
  {
    try
    {
      this.sourceSocket.close();
    }
    catch (IOException e)
    {
      e.printStackTrace();
    }
    
    try
    {
      this.targetSocket.close();
    }
    catch (IOException e)
    {
      e.printStackTrace();
    }
    
    this.sender.interrupt();
    this.receiver.interrupt();
  }
  
  private class TransmitRelaySender extends Thread
  {
    
    public TransmitRelaySender()
    {
      super.setName("TransmitRelaySender");
      super.setDaemon(false);
    }

    public void run()
    {
      try
      {
        Log.global.info("socket[", TransmitRelayConnector.this.sourceSocket.getInetAddress().getHostAddress(), ":", TransmitRelayConnector.this.sourceSocket.getPort(), "] request connect to [" + TransmitRelayConnector.this.remoteHost + ":" + TransmitRelayConnector.this.remotePort + "]");
        IOUtils.readToWrite(TransmitRelayConnector.this.targetSocket.getInputStream(), TransmitRelayConnector.this.sourceSocket.getOutputStream());
      }
      catch (IOException e)
      {
//        e.printStackTrace();
      }
      finally
      {
        if (!TransmitRelayConnector.this.printFlag)
        {
          TransmitRelayConnector.this.printFlag = true;
          Log.global.info("disconnect socket[", TransmitRelayConnector.this.sourceSocket.getInetAddress().getHostAddress(), ":", TransmitRelayConnector.this.sourceSocket.getPort(), "]");
        }
        
        TransmitRelayConnector.this.disconnect();
      }
    }
    
  }
  
  private class TransmitRelayReceiver extends Thread
  {
    
    public TransmitRelayReceiver()
    {
      super.setName("TransmitRelayReceiver");
      super.setDaemon(false);
    }

    public void run()
    {
      try
      {
        IOUtils.readToWrite(TransmitRelayConnector.this.sourceSocket.getInputStream(), TransmitRelayConnector.this.targetSocket.getOutputStream());
      }
      catch (IOException e)
      {
//        e.printStackTrace();
        
        if (!TransmitRelayConnector.this.printFlag)
        {
          TransmitRelayConnector.this.printFlag = true;
          Log.global.info("disconnect socket[", TransmitRelayConnector.this.sourceSocket.getInetAddress().getHostAddress(), ":", TransmitRelayConnector.this.sourceSocket.getPort(), "]");
        }
      }
      finally
      {
//        System.out.println("recv exit...");
        TransmitRelayConnector.this.disconnect();
      }
    }
    
  }
  
}
